﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD.Helper {
    /// <summary>
    /// 数値演算クラス
    /// </summary>
    public static class MyMath {
        /// <summary>
        /// 配列同士の引き算
        /// </summary>
        /// <param name="arry1">配列1</param>
        /// <param name="arry2">配列2</param>
        /// <returns>計算結果</returns>
        public static float[] Subtract (float[] arry1, float[] arry2) {
            var arry = new float[arry1.Length];
            for (var i = 0; i < arry1.Length; i++) {
                arry[i] = arry1[i] - arry2[i];
            }
            return arry;
        }

        /// <summary>
        /// 配列同士の足し算
        /// </summary>
        /// <param name="arry1">配列1</param>
        /// <param name="arry2">配列2</param>
        /// <returns></returns>
        public static float[] Add (float[] arry1, float[] arry2) {
            var arry = new float[arry1.Length];
            for (var i = 0; i < arry1.Length; i++) {
                arry[i] = arry1[i] + arry2[i];
            }
            return arry;
        }

        /// <summary>
        /// 配列にfloat値をかけて足す
        /// </summary>
        /// <remarks>
        /// <paramref name="arry2"/>に<paramref name="m"/>をかけて<paramref name="arry1"/>を足す
        /// </remarks>
        /// <param name="arry1">配列1</param>
        /// <param name="arry2">配列2</param>
        /// <param name="m">float値</param>
        /// <returns></returns>
        public static float[] AddMultiply (float[] arry1, float[] arry2, float m) {
            var arry = new float[arry1.Length];
            for (var i = 0; i < arry1.Length; i++) {
                arry[i] = arry1[i] + arry2[i] * m;
            }
            return arry;
        }

        /// <summary>
        /// 指定の浮動小数値をByte型[0,255]にクランプする
        /// </summary>
        /// <param name="value">任意の値</param>
        /// <returns>Byte型にクランプされた値</returns>
        public static byte ClampToByte (float value) {
            return (byte)Math.Min (Byte.MaxValue, Math.Max (Byte.MinValue, value));
        }

        /// <summary>
        /// 指定の浮動小数値をSByte型[-127,128]にクランプする
        /// </summary>
        /// <param name="value">任意の値</param>
        /// <returns>SByte型にクランプされた値</returns>
        public static sbyte ClampToSByte (float value) {
            return (sbyte)Math.Min (SByte.MaxValue, Math.Max (SByte.MinValue, value));
        }

        /// <summary>
        /// 指定の浮動小数値をShort型[-32767,32768]にクランプする
        /// </summary>
        /// <param name="value">任意の値</param>
        /// <returns>Short型にクランプされた値</returns>
        public static short ClampToShort (float value) {
            return (short)Math.Min (Int16.MaxValue, Math.Max (Int16.MinValue, value));
        }

        /// <summary>
        /// 指定の浮動小数値をUShort型[0,65535]にクランプする
        /// </summary>
        /// <param name="value">任意の値</param>
        /// <returns>UShort型にクランプされた値</returns>
        public static ushort ClampToUShort (float value) {
            return (ushort)Math.Min (UInt16.MaxValue, Math.Max (UInt16.MinValue, value));
        }

        /// <summary>
        /// 指定の浮動小数値をINT型[-2147483648,2147483647]にクランプする
        /// </summary>
        /// <param name="value">任意の値</param>
        /// <returns>INT型にクランプされた値</returns>
        public static int ClampToInt (float value) {
            return (int)Math.Min (Int32.MaxValue, Math.Max (Int32.MinValue, (double)value));
        }

        /// <summary>
        /// 指定の浮動小数値をUINT型[0,4294967295]にクランプする
        /// </summary>
        /// <param name="value">任意の値</param>
        /// <returns>UINT型にクランプされた値</returns>
        public static uint ClampToUInt (float value) {
            var a = Math.Max (UInt32.MinValue, (double)value);
            var b = Math.Min (UInt32.MaxValue, a);
            var c = (uint)b;
            return (uint)Math.Min (UInt32.MaxValue, Math.Max (UInt32.MinValue, (double)value));
        }


    }

}
